package com.siyuanren.gcocp.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.siyuanren.gcocp.common.config.PublicConfig;
import com.siyuanren.gcocp.common.util.UUIDUitl;
import com.siyuanren.gcocp.consts.GcocpConsts;
import com.siyuanren.gcocp.dto.ActiveInviteDTO;
import com.siyuanren.gcocp.entity.*;
import com.siyuanren.gcocp.factory.WxTemplateMsgFac;
import com.siyuanren.gcocp.mapper.MyWxActiveMapper;
import com.siyuanren.gcocp.mapper.MyWxUserVoucherMapper;
import com.siyuanren.gcocp.mapper.base.*;
import com.siyuanren.gcocp.service.*;
import com.siyuanren.gcocp.task.WxTask;
import com.siyuanren.gcocp.util.NewImageUtil;
import com.siyuanren.gcocp.util.ObjectUtil;
import com.siyuanren.gcocp.util.QrCodeCreateUtil;
import com.siyuanren.gcocp.vo.QueryActiveVO;
import com.siyuanren.gcocp.vo.SendVoucherVO;
import com.siyuanren.gcocp.vo.StartActiveVO;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * Created by   anxing
 * Project_name gcocp-parent
 * Path         com.siyuanren.gcocp.service.impl
 * Date         2018/6/8
 * Time         15:16
 * Description
 */
@Slf4j
@Service
public class ActiveServiceImpl implements ActiveService {
    @Autowired
    MyWxActiveMapper activeMapper;
    @Autowired
    WxUserActiveMapper userActiveMapper;
    @Autowired
    private WxVoucherMapper voucherMapper;
    @Autowired
    private MyWxUserVoucherMapper userVoucherMapper;
    @Autowired
    private CourseService courseService;
    @Autowired
    private WxUserCourseMapper userCourseMapper;
    @Autowired
    private MsgService msgService;
    @Autowired
    private WxUserService userService;
    @Autowired
    private WxUserTimerTaskMapper userTimerTaskMapper;
    @Autowired
    private WxTemplateMsgMapper templateMsgMapper;

    @Override
    public WxActive getById(Integer id) {
        return activeMapper.selectByPrimaryKey(id);
    }

    @Override
    public ActiveInviteDTO getActiveDetail(QueryActiveVO activeVO) {
        ActiveInviteDTO dto = activeMapper.getActiveDetail(activeVO);
        if (dto != null) {
            dto.setRestTime(DateUtil.date().between(dto.getActiveEndDate(), DateUnit.SECOND));
            dto.setPlayerList(userVoucherMapper.getActivePlayer(activeVO));
            WxUserActiveExample example = new WxUserActiveExample();
            example.or().andUserIdEqualTo(activeVO.getUserId()).andActiveIdEqualTo(activeVO.getActiveId());
            List<WxUserActive> wxUserActives = userActiveMapper.selectByExample(example);
            // 设置是否加入活动
            if (wxUserActives.size() > 0) {
                dto.setJoined(true);
            }
            // 设置完成活动人数
            WxUserActiveExample activeExample = new WxUserActiveExample();
            activeExample.or().andActiveIdEqualTo(activeVO.getActiveId());
            long count = userActiveMapper.countByExample(activeExample);
            dto.setActiveSucessCount((int) count);

            // 判断活动是否正在进行
            if (!ObjectUtil.isEmpty(dto.getId())) {
                WxActiveExample exma = new WxActiveExample();
                Date now = new Date();
                exma.or().andIdEqualTo(dto.getId())
                        .andAvailableEqualTo(true)
                        .andActiveStartDateLessThanOrEqualTo(now)
                        .andActiveEndDateGreaterThan(com.siyuanren.gcocp.util.DateUtil.getDateBefore(now, 1));
                List<WxActive> wxActives = activeMapper.selectByExample(exma);
                if (!wxActives.isEmpty()) {
                    dto.setInProgress(true);
                }
            }
        }
        return dto;
    }

    @Override
    @Transactional
    public void startActive(StartActiveVO vo) throws WxErrorException, IOException {
        WxUser user = userService.getById(vo.getUserId());
        WxUserActiveExample example = new WxUserActiveExample();
        example.or().andActiveIdEqualTo(vo.getActiveId()).andUserIdEqualTo(vo.getUserId());
        List<WxUserActive> userActives = userActiveMapper.selectByExample(example);
        String activeQrcodePath;
        if (userActives.size() > 0) {
         // 已经参加了活动
            activeQrcodePath = userActives.get(0).getActiveUrl();
            //@TODO 调试, 每次都生成图片,稳定后删除.
            WxActive active = activeMapper.selectByPrimaryKey(vo.getActiveId());
            WxVoucher voucher = voucherMapper.selectByPrimaryKey(active.getFollowVoucherId());
            activeQrcodePath = QrCodeCreateUtil.genActiveQRcode(user, voucher.getCourseId(), active, voucher.getId());
        } else {
            WxActive active = activeMapper.selectByPrimaryKey(vo.getActiveId());
            WxVoucher voucher = voucherMapper.selectByPrimaryKey(active.getFollowVoucherId());
            activeQrcodePath = QrCodeCreateUtil.genActiveQRcode(user, voucher.getCourseId(), active, voucher.getId());
            WxUserActive userActive = new WxUserActive();
            userActive.setActiveId(vo.getActiveId());
            userActive.setUserId(vo.getUserId());
            userActive.setActiveUrl(activeQrcodePath);
            userActiveMapper.insertSelective(userActive);

            // 微信提醒
            String courseName = courseService.getByActive(vo.getActiveId()).getCourseName();
            sendActiveStartMsg(user, active);
            timerActiveRemindEveryday(active, vo.getUserId(),courseName);
            timerActiveRemindLastDay(active, vo.getUserId(), courseName);
            timerActiveRemindLast4hour(active, vo.getUserId(), courseName);
        }

        // 向微信用户发送图片
        File file = FileUtil.file(PublicConfig.USER_DATA_PATH + activeQrcodePath);
        msgService.sendFileToUser(user.getOpenid(), file);
    }

    /**
     * 发送活动开始通知
     * @param user
     * @param active
     */
    private void sendActiveStartMsg(WxUser user, WxActive active) {
        WxCourse course = courseService.getSponsorCourseByActive(active.getId());
        WxTemplateMsg msg = WxTemplateMsgFac.getActiveStartMsg(active);
        msgService.sendTemplateMessage(user.getOpenid(), msg);
    }
    /**
     * 活动每日提醒
     * @param active
     * @param userId
     * @param courseNme
     */
    private void timerActiveRemindEveryday(WxActive active, Integer userId, String courseNme) {
        WxTemplateMsg msg = WxTemplateMsgFac.getActiveRemindMsg(courseNme, active);
        templateMsgMapper.insertSelective(msg);
        WxUserTimerTask task = new WxUserTimerTask();
        task.setTemplateMsgId(msg.getId());
        task.setStartDate(com.siyuanren.gcocp.util.DateUtil.getDateAfter(active.getActiveStartDate(), 1));
        task.setEndDate(com.siyuanren.gcocp.util.DateUtil.getDateBefore(active.getActiveEndDate(), 1));
        task.setSendTime(WxTask.Time_7);
        task.setUserOpenId(userService.getById(userId).getOpenid());
        userTimerTaskMapper.insertSelective(task);
    }

    /**
     * 活动最后一天提醒
     * @param active
     * @param userId
     * @param courseNme
     */
    private void timerActiveRemindLastDay(WxActive active, Integer userId, String courseNme) {
        WxTemplateMsg msg = WxTemplateMsgFac.getActiveLastdayRemindMsg(active, courseNme);
        templateMsgMapper.insertSelective(msg);
        WxUserTimerTask task = new WxUserTimerTask();
        task.setTemplateMsgId(msg.getId());
        task.setStartDate(active.getActiveEndDate());
        task.setEndDate(active.getActiveEndDate());
        task.setSendTime(WxTask.Time_7);
        task.setUserOpenId(userService.getById(userId).getOpenid());
        userTimerTaskMapper.insertSelective(task);
    }

    /**
     * 活动最后4小时提醒
     * @param active
     * @param userId
     * @param courseNme
     */
    private void timerActiveRemindLast4hour(WxActive active, Integer userId, String courseNme) {
        WxTemplateMsg msg = WxTemplateMsgFac.getActiveLast4HourRemindMsg(active, courseNme);
        templateMsgMapper.insertSelective(msg);
        WxUserTimerTask task = new WxUserTimerTask();
        task.setTemplateMsgId(msg.getId());
        task.setStartDate(active.getActiveEndDate());
        task.setEndDate(active.getActiveEndDate());
        task.setSendTime(WxTask.Time_7);
        task.setUserOpenId(userService.getById(userId).getOpenid());
        userTimerTaskMapper.insertSelective(task);
    }

    @Override
    @Transactional
    public void sendVoucher(SendVoucherVO vo) {
        WxUserCourseExample exam = new WxUserCourseExample();
        exam.or().andCourseIdEqualTo(vo.getCourseId()).andUserIdEqualTo(vo.getUserId());
        if (userCourseMapper.countByExample(exam) > 0) {
            // 本课程已经购买,不可再次领取优惠券
            return;
        }

        // 如果优惠券领取过,则不可重复领取
        WxUserVoucherExample vuExam = new WxUserVoucherExample();
        vuExam.or().andUserIdEqualTo(vo.getUserId()).andVoucherIdEqualTo(vo.getVoucherId());
        List<WxUserVoucher> list = userVoucherMapper.selectByExample(vuExam);
        if (list.isEmpty()) {
            WxVoucher voucher = voucherMapper.selectByPrimaryKey(vo.getVoucherId());
            WxUserVoucher userVoucher = new WxUserVoucher();
            userVoucher.setUserId(vo.getUserId());
            userVoucher.setSponsorUserId(vo.getSponsorUserId());
            userVoucher.setActiveId(vo.getActiveId());
            userVoucher.setVoucherId(vo.getVoucherId());
            userVoucher.setVoucherTitle(voucher.getTitle());
            userVoucher.setVoucherFee(voucher.getFee());
            userVoucher.setVoucherOverdueDate(com.siyuanren.gcocp.util.DateUtil.getDateAfter(new Date(), voucher.getValidTime()));
            userVoucher.setVoucherType(voucher.getType());
            userVoucher.setVoucherCourseId(voucher.getCourseId());
            userVoucherMapper.insertSelective(userVoucher);

            // 只有优惠券的发送人和领取人不是同一个人时,才发送优惠卷通知.
            if (vo.getUserId() != vo.getSponsorUserId() && vo.getSponsorUserId() != null) {
                sendFriendReceiveVoucherMsg(userVoucher);
            }
        }
    }

    /**
     * 发送好友领取优惠券通知
     * @param userVoucher
     */
    private void sendFriendReceiveVoucherMsg(WxUserVoucher userVoucher) {
        WxUser user = userService.getById(userVoucher.getUserId());
        WxUser sponsorUser = userService.getById(userVoucher.getSponsorUserId());
        WxTemplateMsg msg = WxTemplateMsgFac.getFriendReceiveVoucherMsg(user, sponsorUser.getNickname());
        msgService.sendTemplateMessage(sponsorUser.getOpenid(), msg);
    }

}
